package org.onion.pattern.event.spring.outbox;


import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.onion.pattern.event.outbox.OutboxEventStorage;
import org.onion.pattern.event.outbox.data.OutboxEventInfo;
import org.onion.pattern.event.outbox.data.OutboxEventStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Component
@Slf4j
public class JdbcOutboxEventStorage implements OutboxEventStorage {

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @Override
    public List<OutboxEventInfo> findReadyEventByGroup(String group, int limit) {
        return jdbcTemplate.query("select " + OutboxEventInfoRowMapper.COLUMNS +
                        " from " + OutboxEventInfoRowMapper.TABLE_NAME
                        + " where event_group = ? and event_status = 0  order by id limit ? for update ", OutboxEventInfoRowMapper.INSTANCE,
                group, limit);
    }

    @Override
    public Optional<OutboxEventInfo> findByEventKey(String eventKey) {
        List<OutboxEventInfo> query = jdbcTemplate.query("select " + OutboxEventInfoRowMapper.COLUMNS +
                " from " + OutboxEventInfoRowMapper.TABLE_NAME +
                " where event_key = ? ", OutboxEventInfoRowMapper.INSTANCE, eventKey);
        if (query.isEmpty()) {
            return Optional.empty();
        }
        return Optional.of(query.get(0));
    }

    @Override
    public void insert(OutboxEventInfo eventInfo) {
        //TODO 是否用异步批量发送 何挺强
        //TODO 如果是异步批量发送，发送完后要做通知 何挺强
        log.debug("【事件存储】 insert {}", eventInfo);
        String sql = "INSERT INTO " + OutboxEventInfoRowMapper.TABLE_NAME + " (" +
                " event_key," +
                " domain_id," +
                " domain_type," +
                " topic," +
                " sub_topic," +
                " event_time," +
                " props," +
                " channel," +
                " serializer," +
                " payload," +
                " event_group," +
                " ver , " +
                " event_status) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";

        this.jdbcTemplate.update(sql, eventInfo.getEventKey(), eventInfo.getDomainId(),
                eventInfo.getDomainType(), eventInfo.getTopic(), eventInfo.getSubTopic(), eventInfo.getEventTime(),
                JSONUtil.toJsonStr(eventInfo.getProps()), eventInfo.getChannel(),
                eventInfo.getSerializer(), eventInfo.getPayload(), eventInfo.getGroup(),
                eventInfo.getVer(), eventInfo.getOutBoxEventStatus().getCode());
    }

    @Override
    public void batchInsert(List<OutboxEventInfo> eventInfo) {
        eventInfo.forEach(this::insert);
        //TODO  2025-08-02 9:19  何挺强
    }

    @Override
    public void ack(Set<String> eventKeys) {
        //TODO 发布时间 2025-08-02 13:16  何挺强
        StringBuilder batchSql = new StringBuilder("update " + OutboxEventInfoRowMapper.TABLE_NAME +
                " set event_status = " + OutboxEventStatus.DELIVERED.getCode() +
                " where event_key in ( ");
        for (String eventKey : eventKeys) {
            batchSql.append(" ?,");
        }
        batchSql.deleteCharAt(batchSql.length() - 1);
        batchSql.append(" )");

        String[] array = eventKeys.toArray(new String[]{});
        int effectRow = this.jdbcTemplate.update(batchSql.toString(), (Object[]) array);
        Assert.isTrue(effectRow > 0,"事件状态更新失败");
    }

    @Override
    public void deleteByEventKey(Set<String> eventKeys) {

    }

}
